Comparison of tg mice ### Import experimental design matrix.


library(DESeq2)
library(pheatmap)
library(dplyr)
library(dendextend)
library(ggplot2)
#Daniela File path
design_matrix<-read.table('/Users/danielaquijano/Documents/GitHub/Transcriptomics-Final-Project-/source_files/Experimental_Design_TG.csv',sep=',',header=TRUE)
head(design_matrix)
design_matrix<-read.table('/Users/tasnimtabassum/Documents/Transcriptomics_SP22/Experimental_Design_TG.csv',sep=',',header=TRUE)
Warning in file(file, "rt") :
  cannot open file '/Users/tasnimtabassum/Documents/Transcriptomics_SP22/Experimental_Design_TG.csv': No such file or directory
Error in file(file, "rt") : cannot open the connection
rownames(design_matrix)<-design_matrix$Sample
design_matrix$Sample<-NULL

design_matrix
counts_matrix<-read.table("/Users/danielaquijano/Documents/GitHub/Transcriptomics-Final-Project-/Count_Tables/allcounts.csv",sep=',',header=TRUE)
counts_matrix

Because the numbers after the dot in the ensembl IDs represent versions of genes in certain annotations, we can remove these to more easily conduct our differential gene expression analysis.

counts_matrix$V1<-gsub("\\..*","",counts_matrix$V1)

counts_matrix
# remove the "V1" from col 1
rownames(counts_matrix)<-counts_matrix$V1
counts_matrix$V1<-NULL

#head(counts_matrix)

counts_matrix<-counts_matrix[,order(colnames(counts_matrix))]
counts_matrix
design_matrix<-design_matrix[order(rownames(design_matrix)),]

design_matrix
NA

design_matrix$Age = factor(design_matrix$Age)

design_matrix$Age
 [1] 8  8  2  2  8  8  2  2  2  8  8  8  2  2  8  8  2  2  2  2  8  8  8  8  2  2  6  6  6  6 
[31] 12 12 12 12 12 12 12 12 6  6  12 12 6  6  12 12 6  6  6  6  12 12 6  6  12 12 6  6  12 12
[61] 12 12 12 12 6  6  6  6  2  2  8  8 
Levels: 2 6 8 12
dds <- DESeqDataSetFromMatrix(countData = counts_matrix,
                              colData = design_matrix,
                              design = ~ Genotype + Age)
Warning in DESeqDataSet(se, design = design, ignoreRank) :
  some variables in design formula are characters, converting to factors
dds
class: DESeqDataSet 
dim: 46075 72 
metadata(1): version
assays(1): counts
rownames(46075): ENSMUSG00000000001 ENSMUSG00000000003 ... N_noFeature N_unmapped
rowData names(0):
colnames(72): SRR8512301 SRR8512302 ... SRR8512439 SRR8512440
colData names(3): Model Genotype Age
keep <- rowSums(counts(dds)) >= 10
dds <- dds[keep,]
dds <- DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 13407 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
normalizedcounts.matrix <- counts(dds,normalized=T)
vst_dds <- vst(dds)

dists <- dist(t(assay(vst_dds)))
head(vst_dds)
class: DESeqTransform 
dim: 6 72 
metadata(1): version
assays(1): ''
rownames(6): ENSMUSG00000000001 ENSMUSG00000000028 ... ENSMUSG00000000049
  ENSMUSG00000000056
rowData names(43): baseMean baseVar ... replace dispFit
colnames(72): SRR8512301 SRR8512302 ... SRR8512439 SRR8512440
colData names(5): Model Genotype Age sizeFactor replaceable


PCA_Genotype<-plotPCA(vst_dds,intgroup=c("Age"))+labs(title = "PCA of mice of different ages", color = "Group")+coord_fixed(ratio=3)
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
PCA_Genotype

resultsNames(dds)
[1] "Intercept"               "Genotype_rtg4510_vs_J20" "Genotype_WT_vs_J20"     
[4] "Genotype_WT_TG_vs_J20"   "Age_6_vs_2"              "Age_8_vs_2"             
[7] "Age_12_vs_2"            
dds$Age
 [1] 8  8  2  2  8  8  2  2  2  8  8  8  2  2  8  8  2  2  2  2  8  8  8  8  2  2  6  6  6  6 
[31] 12 12 12 12 12 12 12 12 6  6  12 12 6  6  12 12 6  6  6  6  12 12 6  6  12 12 6  6  12 12
[61] 12 12 12 12 6  6  6  6  2  2  8  8 
Levels: 2 6 8 12
#Compare 2 vs 8
res_1 <- results(dds, contrast = c("Age", "2", "8"))
res1_ordered <- res_1[order(res_1$padj),] 
head(res1_ordered)
log2 fold change (MLE): Age 2 vs 8 
Wald test p-value: Age 2 vs 8 
DataFrame with 6 rows and 6 columns
                    baseMean log2FoldChange     lfcSE      stat      pvalue        padj
                   <numeric>      <numeric> <numeric> <numeric>   <numeric>   <numeric>
ENSMUSG00000024501 1037.7531       0.574615 0.0533228  10.77617 4.46087e-27 8.33424e-23
ENSMUSG00000030577   10.9689      -4.378147 0.4088869 -10.70748 9.38860e-27 8.77036e-23
ENSMUSG00000026303   45.6887      -1.152385 0.1270487  -9.07042 1.18561e-19 7.38360e-16
ENSMUSG00000030124  162.9878      -1.526436 0.1688798  -9.03859 1.58702e-19 7.41256e-16
ENSMUSG00000046805  863.4728      -1.317521 0.1476032  -8.92610 4.41285e-19 1.64891e-15
ENSMUSG00000029816   69.7214      -1.694820 0.1920512  -8.82483 1.09623e-18 3.41348e-15

Install Mouse annotation library:

library(biomaRt) #For conversion of transcript IDs to gene ID
library(annotables) #to retrieve grcm38 annotation for mouse genome
library(org.Mm.eg.db) #Mouse genome annotation
library(DOSE)
library(pathview)
library(clusterProfiler)
library(AnnotationHub) 
library(ensembldb)
library(tidyverse)
library(ggnewscale)
# mouse genome load
grcm38

# check that ensgene in our df is prsent in the mouse genome df

idx <- grcm38$ensgene %in% rownames(res1_ordered)
# head(idx)

# df with all the ids that are in our df from the mouse genome df
ids <- grcm38[idx, ]

# head(ids)

# remove duplicates

non_duplicates <- which(duplicated(ids$ensgene) == FALSE)
ids <- ids[non_duplicates, ]

#nrow(res1_ordered)

#rownames(res1_ordered)

# entrezID contains only the IDs that are also in our df

ensgeneID= grcm38[grcm38$ensgene %in% rownames(res1_ordered), ]

# entrezID contains only the IDs that are also in our df

entrezID= grcm38[grcm38$ensgene %in% rownames(res1_ordered), ]
# check nrow ensgeneID
head(ensgeneID)

# create a vector of only the ensgeneIDs
ensgene_ID_vector = c(ensgeneID[[1]])

head(ensgene_ID_vector)
[1] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000031" "ENSMUSG00000000037"
[5] "ENSMUSG00000000049" "ENSMUSG00000000056"
# create a vector of only the entrezIDs
entrez_ID_vector = c(entrezID[[2]])

# create a vector of only the gene symbols
gene_symbols = subset(grcm38$symbol, grcm38$ensgene %in% rownames(res1_ordered))

# create new df that contains only the ensgeneIDs, lfc and padj
res2= data.frame(log2foldchange= subset(res1_ordered$log2FoldChange, grcm38$ensgene %in% rownames(res1_ordered)))
padj = subset(res1_ordered$padj, grcm38$ensgene %in% rownames(res1_ordered))
res2 = cbind(padj, res2)
res2 = cbind(ensgene_ID_vector, res2)
res2 = cbind(entrez_ID_vector, res2)
res2 = cbind(gene_symbols, res2)


# omit all "na" values
res2 = na.omit(res2)

res2 <- res2[order(res2$padj),] 
head(res2)
## Significant genes is a vector of fold changes where the names are ENTREZ gene IDs. The background set is a vector of all the genes represented on the platform.

# bg entrez contains all the ensgene

allOEgenes = as.character(res2$ensgene_ID_vector)

# sig res entrez contains all the entrezIDs that have padj <0.05
head(res2)

sigOE <- subset(res2, padj< 0.05)

head(sigOE)
# vector of only lfc values
sigOE_genes = as.character(sigOE$ensgene_ID_vector)

head(sigOE_genes)
[1] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000037" "ENSMUSG00000000049"
[5] "ENSMUSG00000000056" "ENSMUSG00000000058"
## Run GO enrichment analysis 
ego <- enrichGO(gene = sigOE_genes, 
                universe = allOEgenes,
                keyType = "ENSEMBL",
                OrgDb = org.Mm.eg.db, 
                ont = "ALL", 
                pAdjustMethod = "none", 
                qvalueCutoff = 0.05, 
                readable = TRUE,
                pool  = TRUE)

                
## Output results from GO analysis to a table
cluster_summary <- data.frame(ego)

#gene_ratio = cluster_summary[order(cluster_summary$pvalue, decreasing = FALSE), ]
#head(gene_ratio)


write.csv(cluster_summary, "WT_TG_vs_rTg4510.csv")
ego
#
# over-representation test
#
#...@organism    Mus musculus 
#...@ontology    GOALL 
#...@keytype     ENSEMBL 
#...@gene    chr [1:3049] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000037" ...
#...pvalues adjusted by 'none' with cutoff <0.05 
#...320 enriched terms found
'data.frame':   320 obs. of  10 variables:
 $ ONTOLOGY   : chr  "BP" "BP" "BP" "BP" ...
 $ ID         : chr  "GO:0072594" "GO:0010632" "GO:0010594" "GO:0017038" ...
 $ Description: chr  "establishment of protein localization to organelle" "regulation of epithelial cell migration" "regulation of endothelial cell migration" "protein import" ...
 $ GeneRatio  : chr  "124/3047" "79/3047" "62/3047" "73/3047" ...
 $ BgRatio    : chr  "368/15222" "224/15222" "163/15222" "203/15222" ...
 $ pvalue     : num  3.36e-10 6.13e-08 7.25e-08 7.86e-08 8.86e-08 ...
 $ p.adjust   : num  3.36e-10 6.13e-08 7.25e-08 7.86e-08 8.86e-08 ...
 $ qvalue     : num  2.22e-06 1.03e-04 1.03e-04 1.03e-04 1.03e-04 ...
 $ geneID     : chr  "Cdh1/Hk2/Oxa1l/Calm1/Cct3/Kpnb1/Jup/Akt1/Smo/Fbxo7/Folr1/Nup214/Bcap31/Bbc3/Ipo4/Tsc2/Tgfb1/Shh/Prkd1/Cse1l/Pex"| __truncated__ "Apoh/Alox12/Pparg/Pdgfb/Acvrl1/Sox9/Krit1/Serpinf1/Il4/Sp1/Itga3/Jup/Marveld3/Akt1/Rin2/Rac1/Tgfb1/Shh/Prkd1/Ap"| __truncated__ "Apoh/Alox12/Pparg/Pdgfb/Acvrl1/Krit1/Serpinf1/Sp1/Jup/Akt1/Rin2/Rac1/Tgfb1/Shh/Prkd1/Apoe/Klf4/Calr/Stat5a/Hdac"| __truncated__ "Cdh1/Kpnb1/Jup/Akt1/Smo/Nup214/Ipo4/Tsc2/Tgfb1/Shh/Prkd1/Cse1l/Pex6/Cd36/Timm44/Tomm40/Apoe/Ranbp2/Timm50/Pex19"| __truncated__ ...
 $ Count      : int  124 79 62 73 123 62 127 123 122 79 ...
#...Citation
 T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu.
 clusterProfiler 4.0: A universal enrichment tool for interpreting omics data.
 The Innovation. 2021, 2(3):100141 
## Dotplot 
dotplot(ego, showCategory=30)+theme(text = element_text(size = 1)) +scale_y_discrete(labels=function(x) str_wrap(x, width=40))+ggtitle('Enriched genes when comparing rTg4510 mice at 2 and 8 months')+ theme(plot.title = element_text(size=16))
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.

#barplot(ego, showCategory = 20)
options(ggrepel.max.overlaps = Inf)

## To color genes by log2 fold changes, we need to extract the log2 fold changes from our results table creating a named vector
OE_foldchanges <- sigOE$log2foldchange

names(OE_foldchanges) <- sigOE$gene_symbols

## Cnetplot details the genes associated with one or more terms - by default gives the top 1 significant term (by padj)

cnetplot(ego, 
         categorySize="pvalue", 
         showCategory = 4,
         colorEdge = TRUE,
         circular = FALSE,
         node_label = "all",
         cex_category = 1.5,
         cex_gene = 0.75,
         cex_label_category = 1.5,
         cex_label_gene = 0.75,
         shadowtext = "all")+ggtitle('Enriched Genes when comparing rTg4510 mice at 2 and 8 months ')

NA
NA
NA
NA
library(enrichplot)
ego2 = pairwise_termsim(ego)
emapplot(ego2, showCategory = 20, colorEdge = TRUE)+ggtitle('Enriched Genes when comparing rTg4510 mice at 2 and 8 months of age')


# Set-up

#BiocManager::install("SPIA")
library(SPIA)
Loading required package: KEGGgraph

Attaching package: 'KEGGgraph'

The following object is masked from 'package:pathview':

    KEGGEdgeSubtype

The following object is masked from 'package:graphics':

    plot

The following object is masked from 'package:base':

    plot
## Significant genes is a vector of fold changes where the names are ENTREZ gene IDs. The background set is a vector of all the genes represented on the platform.

# bg entrez contains all the entrezIDs 

background_entrez <- res2$entrez_ID_vector

# sig res entrez contains all the entrezIDs that have padj <0.05

sig_res_entrez <- res2[which(res2$padj < 0.05), ]

# vector of only lfc values
sig_entrez <- sig_res_entrez$log2foldchange

head(sig_entrez)
[1]  0.574615 -1.152385 -1.317521 -1.694820 -1.351549 -1.217587
# adding entrezIDs as names for the sig entrez
names(sig_entrez) <- sig_res_entrez$entrez_ID_vector

head(sig_entrez)
    14679     12544    107815     11818     67608     12390 
 0.574615 -1.152385 -1.317521 -1.694820 -1.351549 -1.217587 
# remove dups
dups<-unique(names(sig_entrez[which(duplicated(names(sig_entrez)))]))
sig_entrez<-sig_entrez[!(names(sig_entrez) %in% dups)]


#de= as.vector(sig_entrez)

#de = sort(de, decreasing = FALSE)

# this step takes time

spia_result <- spia(de=sig_entrez, all=background_entrez, organism="mmu", plots=FALSE)
write.csv(spia_result, file = "spia_result_tg_age.csv")

# view one record at a time

subset(spia_result, ID == "04727")

head(res1_ordered)
log2 fold change (MLE): Age 2 vs 8 
Wald test p-value: Age 2 vs 8 
DataFrame with 6 rows and 6 columns
                    baseMean log2FoldChange     lfcSE      stat      pvalue        padj
                   <numeric>      <numeric> <numeric> <numeric>   <numeric>   <numeric>
ENSMUSG00000024501 1037.7531       0.574615 0.0533228  10.77617 4.46087e-27 8.33424e-23
ENSMUSG00000030577   10.9689      -4.378147 0.4088869 -10.70748 9.38860e-27 8.77036e-23
ENSMUSG00000026303   45.6887      -1.152385 0.1270487  -9.07042 1.18561e-19 7.38360e-16
ENSMUSG00000030124  162.9878      -1.526436 0.1688798  -9.03859 1.58702e-19 7.41256e-16
ENSMUSG00000046805  863.4728      -1.317521 0.1476032  -8.92610 4.41285e-19 1.64891e-15
ENSMUSG00000029816   69.7214      -1.694820 0.1920512  -8.82483 1.09623e-18 3.41348e-15
norm_counts_top_40 = normalizedcounts.matrix[row.names(head(res1_ordered, 40)), ]
nrow(norm_counts_top_40)
[1] 40
head(design_matrix)

annotation_columns<-design_matrix

row.names(annotation_columns) <- colnames(norm_counts_top_40)

library(pheatmap)

tiff("Heatmap_WT_TG_vs_rtg4510.tiff", width = 7, height = 5, units = 'in', res = 300)
pheatmap(norm_counts_top_40, color=colorRampPalette(c("white", "lavender", "darkorchid1"))(30), scale="row", cluster_cols = T, show_rownames = T,fontsize = 7,fontsize_row = 4, fontsize_col = 4,labels_row = rownames(dists),annotation_col =annotation_columns,main='Differentially Expressed Genes in rTg4510 mice at 2 and 8 months old' )
dev.off()
null device 
          1 
LS0tCnRpdGxlOiAiQ2x1c3RlclByb2ZpbGVyIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpDb21wYXJpc29uIG9mIHRnIG1pY2UKIyMjIEltcG9ydCBleHBlcmltZW50YWwgZGVzaWduIG1hdHJpeC4KCmBgYHtyfQoKbGlicmFyeShERVNlcTIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZGVuZGV4dGVuZCkKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCmBgYHtyfQojRGFuaWVsYSBGaWxlIHBhdGgKZGVzaWduX21hdHJpeDwtcmVhZC50YWJsZSgnL1VzZXJzL2RhbmllbGFxdWlqYW5vL0RvY3VtZW50cy9HaXRIdWIvVHJhbnNjcmlwdG9taWNzLUZpbmFsLVByb2plY3QtL3NvdXJjZV9maWxlcy9FeHBlcmltZW50YWxfRGVzaWduX1RHLmNzdicsc2VwPScsJyxoZWFkZXI9VFJVRSkKaGVhZChkZXNpZ25fbWF0cml4KQpgYGAKCmBgYHtyfQojVGFzbmltIEZpbGUgcGF0aAojZGVzaWduX21hdHJpeDwtcmVhZC50YWJsZSgnL1VzZXJzL3Rhc25pbXRhYmFzc3VtL0RvY3VtZW50cy9UcmFuc2NyaXB0b21pY3NfU1AyMi9FeHBlcmltZW50YWxfRGVzaWduX1RHLmNzdicsc2VwPScsJyxoZWFkZXI9VFJVRSkKCiNoZWFkKGRlc2lnbl9tYXRyaXgpCmBgYAoKYGBge3J9CnJvd25hbWVzKGRlc2lnbl9tYXRyaXgpPC1kZXNpZ25fbWF0cml4JFNhbXBsZQpkZXNpZ25fbWF0cml4JFNhbXBsZTwtTlVMTAoKZGVzaWduX21hdHJpeApgYGAKCmBgYHtyfQpjb3VudHNfbWF0cml4PC1yZWFkLnRhYmxlKCIvVXNlcnMvZGFuaWVsYXF1aWphbm8vRG9jdW1lbnRzL0dpdEh1Yi9UcmFuc2NyaXB0b21pY3MtRmluYWwtUHJvamVjdC0vQ291bnRfVGFibGVzL2FsbGNvdW50cy5jc3YiLHNlcD0nLCcsaGVhZGVyPVRSVUUpCmNvdW50c19tYXRyaXgKYGBgCgoKCkJlY2F1c2UgdGhlIG51bWJlcnMgYWZ0ZXIgdGhlIGRvdCBpbiB0aGUgZW5zZW1ibCBJRHMgcmVwcmVzZW50IHZlcnNpb25zIG9mIGdlbmVzIGluIGNlcnRhaW4gYW5ub3RhdGlvbnMsIHdlIGNhbiByZW1vdmUgdGhlc2UgdG8gbW9yZSBlYXNpbHkgY29uZHVjdCBvdXIgZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcy4gCmBgYHtyfQpjb3VudHNfbWF0cml4JFYxPC1nc3ViKCJcXC4uKiIsIiIsY291bnRzX21hdHJpeCRWMSkKCmNvdW50c19tYXRyaXgKYGBgCgpgYGB7cn0KIyByZW1vdmUgdGhlICJWMSIgZnJvbSBjb2wgMQpyb3duYW1lcyhjb3VudHNfbWF0cml4KTwtY291bnRzX21hdHJpeCRWMQpjb3VudHNfbWF0cml4JFYxPC1OVUxMCgojaGVhZChjb3VudHNfbWF0cml4KQoKY291bnRzX21hdHJpeDwtY291bnRzX21hdHJpeFssb3JkZXIoY29sbmFtZXMoY291bnRzX21hdHJpeCkpXQpjb3VudHNfbWF0cml4CmBgYAoKYGBge3J9CmRlc2lnbl9tYXRyaXg8LWRlc2lnbl9tYXRyaXhbb3JkZXIocm93bmFtZXMoZGVzaWduX21hdHJpeCkpLF0KCmRlc2lnbl9tYXRyaXgKCmBgYAoKYGBge3J9CgpkZXNpZ25fbWF0cml4JEFnZSA9IGZhY3RvcihkZXNpZ25fbWF0cml4JEFnZSkKCmRlc2lnbl9tYXRyaXgkQWdlCgoKZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gY291bnRzX21hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGRlc2lnbl9tYXRyaXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH4gR2Vub3R5cGUgKyBBZ2UpCmRkcwoKa2VlcCA8LSByb3dTdW1zKGNvdW50cyhkZHMpKSA+PSAxMApkZHMgPC0gZGRzW2tlZXAsXQpgYGAKCgpgYGB7cn0KZGRzIDwtIERFU2VxKGRkcykKYGBgCgpgYGB7cn0Kbm9ybWFsaXplZGNvdW50cy5tYXRyaXggPC0gY291bnRzKGRkcyxub3JtYWxpemVkPVQpCgpgYGAKCgpgYGB7cn0KdnN0X2RkcyA8LSB2c3QoZGRzKQoKZGlzdHMgPC0gZGlzdCh0KGFzc2F5KHZzdF9kZHMpKSkKaGVhZCh2c3RfZGRzKQpgYGAKCgpgYGB7cn0KCgpQQ0FfR2Vub3R5cGU8LXBsb3RQQ0EodnN0X2RkcyxpbnRncm91cD1jKCJBZ2UiKSkrbGFicyh0aXRsZSA9ICJQQ0Egb2YgbWljZSBvZiBkaWZmZXJlbnQgYWdlcyIsIGNvbG9yID0gIkdyb3VwIikrY29vcmRfZml4ZWQocmF0aW89MykKClBDQV9HZW5vdHlwZQpgYGAKCmBgYHtyfQpyZXN1bHRzTmFtZXMoZGRzKQpgYGAKYGBge3J9CmRkcyRBZ2UKYGBgCgpgYGB7cn0KI0NvbXBhcmUgMiB2cyA4CnJlc18xIDwtIHJlc3VsdHMoZGRzLCBjb250cmFzdCA9IGMoIkFnZSIsICIyIiwgIjgiKSkKcmVzMV9vcmRlcmVkIDwtIHJlc18xW29yZGVyKHJlc18xJHBhZGopLF0gCmhlYWQocmVzMV9vcmRlcmVkKQpgYGAKCkluc3RhbGwgTW91c2UgYW5ub3RhdGlvbiBsaWJyYXJ5OgoKYGBge3J9CmxpYnJhcnkoYmlvbWFSdCkgI0ZvciBjb252ZXJzaW9uIG9mIHRyYW5zY3JpcHQgSURzIHRvIGdlbmUgSUQKbGlicmFyeShhbm5vdGFibGVzKSAjdG8gcmV0cmlldmUgZ3JjbTM4IGFubm90YXRpb24gZm9yIG1vdXNlIGdlbm9tZQpsaWJyYXJ5KG9yZy5NbS5lZy5kYikgI01vdXNlIGdlbm9tZSBhbm5vdGF0aW9uCmxpYnJhcnkoRE9TRSkKbGlicmFyeShwYXRodmlldykKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkoQW5ub3RhdGlvbkh1YikgCmxpYnJhcnkoZW5zZW1ibGRiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ25ld3NjYWxlKQpgYGAKCmBgYHtyfQojIG1vdXNlIGdlbm9tZSBsb2FkCmdyY20zOAoKIyBjaGVjayB0aGF0IGVuc2dlbmUgaW4gb3VyIGRmIGlzIHByc2VudCBpbiB0aGUgbW91c2UgZ2Vub21lIGRmCgppZHggPC0gZ3JjbTM4JGVuc2dlbmUgJWluJSByb3duYW1lcyhyZXMxX29yZGVyZWQpCiMgaGVhZChpZHgpCgojIGRmIHdpdGggYWxsIHRoZSBpZHMgdGhhdCBhcmUgaW4gb3VyIGRmIGZyb20gdGhlIG1vdXNlIGdlbm9tZSBkZgppZHMgPC0gZ3JjbTM4W2lkeCwgXQoKIyBoZWFkKGlkcykKCiMgcmVtb3ZlIGR1cGxpY2F0ZXMKCm5vbl9kdXBsaWNhdGVzIDwtIHdoaWNoKGR1cGxpY2F0ZWQoaWRzJGVuc2dlbmUpID09IEZBTFNFKQppZHMgPC0gaWRzW25vbl9kdXBsaWNhdGVzLCBdCmBgYAoKYGBge3J9CgojbnJvdyhyZXMxX29yZGVyZWQpCgojcm93bmFtZXMocmVzMV9vcmRlcmVkKQoKIyBlbnRyZXpJRCBjb250YWlucyBvbmx5IHRoZSBJRHMgdGhhdCBhcmUgYWxzbyBpbiBvdXIgZGYKCmVuc2dlbmVJRD0gZ3JjbTM4W2dyY20zOCRlbnNnZW5lICVpbiUgcm93bmFtZXMocmVzMV9vcmRlcmVkKSwgXQoKIyBlbnRyZXpJRCBjb250YWlucyBvbmx5IHRoZSBJRHMgdGhhdCBhcmUgYWxzbyBpbiBvdXIgZGYKCmVudHJleklEPSBncmNtMzhbZ3JjbTM4JGVuc2dlbmUgJWluJSByb3duYW1lcyhyZXMxX29yZGVyZWQpLCBdCiMgY2hlY2sgbnJvdyBlbnNnZW5lSUQKaGVhZChlbnNnZW5lSUQpCgojIGNyZWF0ZSBhIHZlY3RvciBvZiBvbmx5IHRoZSBlbnNnZW5lSURzCmVuc2dlbmVfSURfdmVjdG9yID0gYyhlbnNnZW5lSURbWzFdXSkKCmhlYWQoZW5zZ2VuZV9JRF92ZWN0b3IpCgoKIyBjcmVhdGUgYSB2ZWN0b3Igb2Ygb25seSB0aGUgZW50cmV6SURzCmVudHJlel9JRF92ZWN0b3IgPSBjKGVudHJleklEW1syXV0pCgojIGNyZWF0ZSBhIHZlY3RvciBvZiBvbmx5IHRoZSBnZW5lIHN5bWJvbHMKZ2VuZV9zeW1ib2xzID0gc3Vic2V0KGdyY20zOCRzeW1ib2wsIGdyY20zOCRlbnNnZW5lICVpbiUgcm93bmFtZXMocmVzMV9vcmRlcmVkKSkKCiMgY3JlYXRlIG5ldyBkZiB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIGVuc2dlbmVJRHMsIGxmYyBhbmQgcGFkagpyZXMyPSBkYXRhLmZyYW1lKGxvZzJmb2xkY2hhbmdlPSBzdWJzZXQocmVzMV9vcmRlcmVkJGxvZzJGb2xkQ2hhbmdlLCBncmNtMzgkZW5zZ2VuZSAlaW4lIHJvd25hbWVzKHJlczFfb3JkZXJlZCkpKQpwYWRqID0gc3Vic2V0KHJlczFfb3JkZXJlZCRwYWRqLCBncmNtMzgkZW5zZ2VuZSAlaW4lIHJvd25hbWVzKHJlczFfb3JkZXJlZCkpCnJlczIgPSBjYmluZChwYWRqLCByZXMyKQpyZXMyID0gY2JpbmQoZW5zZ2VuZV9JRF92ZWN0b3IsIHJlczIpCnJlczIgPSBjYmluZChlbnRyZXpfSURfdmVjdG9yLCByZXMyKQpyZXMyID0gY2JpbmQoZ2VuZV9zeW1ib2xzLCByZXMyKQoKCiMgb21pdCBhbGwgIm5hIiB2YWx1ZXMKcmVzMiA9IG5hLm9taXQocmVzMikKCnJlczIgPC0gcmVzMltvcmRlcihyZXMyJHBhZGopLF0gCmhlYWQocmVzMikKYGBgCgpgYGB7cn0KIyMgU2lnbmlmaWNhbnQgZ2VuZXMgaXMgYSB2ZWN0b3Igb2YgZm9sZCBjaGFuZ2VzIHdoZXJlIHRoZSBuYW1lcyBhcmUgRU5UUkVaIGdlbmUgSURzLiBUaGUgYmFja2dyb3VuZCBzZXQgaXMgYSB2ZWN0b3Igb2YgYWxsIHRoZSBnZW5lcyByZXByZXNlbnRlZCBvbiB0aGUgcGxhdGZvcm0uCgojIGJnIGVudHJleiBjb250YWlucyBhbGwgdGhlIGVuc2dlbmUKCmFsbE9FZ2VuZXMgPSBhcy5jaGFyYWN0ZXIocmVzMiRlbnNnZW5lX0lEX3ZlY3RvcikKCiMgc2lnIHJlcyBlbnRyZXogY29udGFpbnMgYWxsIHRoZSBlbnRyZXpJRHMgdGhhdCBoYXZlIHBhZGogPDAuMDUKaGVhZChyZXMyKQoKc2lnT0UgPC0gc3Vic2V0KHJlczIsIHBhZGo8IDAuMDUpCgpoZWFkKHNpZ09FKQojIHZlY3RvciBvZiBvbmx5IGxmYyB2YWx1ZXMKc2lnT0VfZ2VuZXMgPSBhcy5jaGFyYWN0ZXIoc2lnT0UkZW5zZ2VuZV9JRF92ZWN0b3IpCgpoZWFkKHNpZ09FX2dlbmVzKQoKYGBgCgoKYGBge3J9CiMjIFJ1biBHTyBlbnJpY2htZW50IGFuYWx5c2lzIAplZ28gPC0gZW5yaWNoR08oZ2VuZSA9IHNpZ09FX2dlbmVzLCAKICAgICAgICAgICAgICAgIHVuaXZlcnNlID0gYWxsT0VnZW5lcywKICAgICAgICAgICAgICAgIGtleVR5cGUgPSAiRU5TRU1CTCIsCiAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5NbS5lZy5kYiwgCiAgICAgICAgICAgICAgICBvbnQgPSAiQUxMIiwgCiAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIm5vbmUiLCAKICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDAuMDUsIAogICAgICAgICAgICAgICAgcmVhZGFibGUgPSBUUlVFLAogICAgICAgICAgICAgICAgcG9vbCAgPSBUUlVFKQoKICAgICAgICAgICAgICAgIAojIyBPdXRwdXQgcmVzdWx0cyBmcm9tIEdPIGFuYWx5c2lzIHRvIGEgdGFibGUKY2x1c3Rlcl9zdW1tYXJ5IDwtIGRhdGEuZnJhbWUoZWdvKQoKI2dlbmVfcmF0aW8gPSBjbHVzdGVyX3N1bW1hcnlbb3JkZXIoY2x1c3Rlcl9zdW1tYXJ5JHB2YWx1ZSwgZGVjcmVhc2luZyA9IEZBTFNFKSwgXQojaGVhZChnZW5lX3JhdGlvKQoKCndyaXRlLmNzdihjbHVzdGVyX3N1bW1hcnksICJXVF9UR192c19yVGc0NTEwLmNzdiIpCgpgYGAKYGBge3J9CmVnbwpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0yMH0KIyMgRG90cGxvdCAKZG90cGxvdChlZ28sIHNob3dDYXRlZ29yeT0zMCkrdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMSkpICtzY2FsZV95X2Rpc2NyZXRlKGxhYmVscz1mdW5jdGlvbih4KSBzdHJfd3JhcCh4LCB3aWR0aD00MCkpK2dndGl0bGUoJ0VucmljaGVkIGdlbmVzIHdoZW4gY29tcGFyaW5nIHJUZzQ1MTAgbWljZSBhdCAyIGFuZCA4IG1vbnRocycpKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYpKQoKI2JhcnBsb3QoZWdvLCBzaG93Q2F0ZWdvcnkgPSAyMCkKYGBgCgoKCgoKYGBge3IgZmlnLndpZHRoPTIwLGZpZy5oZWlnaHQ9MjB9Cm9wdGlvbnMoZ2dyZXBlbC5tYXgub3ZlcmxhcHMgPSBJbmYpCgojIyBUbyBjb2xvciBnZW5lcyBieSBsb2cyIGZvbGQgY2hhbmdlcywgd2UgbmVlZCB0byBleHRyYWN0IHRoZSBsb2cyIGZvbGQgY2hhbmdlcyBmcm9tIG91ciByZXN1bHRzIHRhYmxlIGNyZWF0aW5nIGEgbmFtZWQgdmVjdG9yCk9FX2ZvbGRjaGFuZ2VzIDwtIHNpZ09FJGxvZzJmb2xkY2hhbmdlCgpuYW1lcyhPRV9mb2xkY2hhbmdlcykgPC0gc2lnT0UkZ2VuZV9zeW1ib2xzCgojIyBDbmV0cGxvdCBkZXRhaWxzIHRoZSBnZW5lcyBhc3NvY2lhdGVkIHdpdGggb25lIG9yIG1vcmUgdGVybXMgLSBieSBkZWZhdWx0IGdpdmVzIHRoZSB0b3AgMSBzaWduaWZpY2FudCB0ZXJtIChieSBwYWRqKQoKY25ldHBsb3QoZWdvLCAKICAgICAgICAgY2F0ZWdvcnlTaXplPSJwdmFsdWUiLCAKICAgICAgICAgc2hvd0NhdGVnb3J5ID0gNCwKICAgICAgICAgY29sb3JFZGdlID0gVFJVRSwKICAgICAgICAgY2lyY3VsYXIgPSBGQUxTRSwKICAgICAgICAgbm9kZV9sYWJlbCA9ICJhbGwiLAogICAgICAgICBjZXhfY2F0ZWdvcnkgPSAxLjUsCiAgICAgICAgIGNleF9nZW5lID0gMC43NSwKICAgICAgICAgY2V4X2xhYmVsX2NhdGVnb3J5ID0gMS41LAogICAgICAgICBjZXhfbGFiZWxfZ2VuZSA9IDAuNzUsCiAgICAgICAgIHNoYWRvd3RleHQgPSAiYWxsIikrZ2d0aXRsZSgnRW5yaWNoZWQgR2VuZXMgd2hlbiBjb21wYXJpbmcgclRnNDUxMCBtaWNlIGF0IDIgYW5kIDggbW9udGhzICcpCiAgICAgICAgIAoKCgpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0yMH0KbGlicmFyeShlbnJpY2hwbG90KQplZ28yID0gcGFpcndpc2VfdGVybXNpbShlZ28pCmVtYXBwbG90KGVnbzIsIHNob3dDYXRlZ29yeSA9IDIwLCBjb2xvckVkZ2UgPSBUUlVFKStnZ3RpdGxlKCdFbnJpY2hlZCBHZW5lcyB3aGVuIGNvbXBhcmluZyByVGc0NTEwIG1pY2UgYXQgMiBhbmQgOCBtb250aHMgb2YgYWdlJykKCmBgYAoKCmBgYHtyfQoKIyBTZXQtdXAKCiNCaW9jTWFuYWdlcjo6aW5zdGFsbCgiU1BJQSIpCmxpYnJhcnkoU1BJQSkKCiMjIFNpZ25pZmljYW50IGdlbmVzIGlzIGEgdmVjdG9yIG9mIGZvbGQgY2hhbmdlcyB3aGVyZSB0aGUgbmFtZXMgYXJlIEVOVFJFWiBnZW5lIElEcy4gVGhlIGJhY2tncm91bmQgc2V0IGlzIGEgdmVjdG9yIG9mIGFsbCB0aGUgZ2VuZXMgcmVwcmVzZW50ZWQgb24gdGhlIHBsYXRmb3JtLgoKIyBiZyBlbnRyZXogY29udGFpbnMgYWxsIHRoZSBlbnRyZXpJRHMgCgpiYWNrZ3JvdW5kX2VudHJleiA8LSByZXMyJGVudHJlel9JRF92ZWN0b3IKCiMgc2lnIHJlcyBlbnRyZXogY29udGFpbnMgYWxsIHRoZSBlbnRyZXpJRHMgdGhhdCBoYXZlIHBhZGogPDAuMDUKCnNpZ19yZXNfZW50cmV6IDwtIHJlczJbd2hpY2gocmVzMiRwYWRqIDwgMC4wNSksIF0KCiMgdmVjdG9yIG9mIG9ubHkgbGZjIHZhbHVlcwpzaWdfZW50cmV6IDwtIHNpZ19yZXNfZW50cmV6JGxvZzJmb2xkY2hhbmdlCgpoZWFkKHNpZ19lbnRyZXopCgoKIyBhZGRpbmcgZW50cmV6SURzIGFzIG5hbWVzIGZvciB0aGUgc2lnIGVudHJlegpuYW1lcyhzaWdfZW50cmV6KSA8LSBzaWdfcmVzX2VudHJleiRlbnRyZXpfSURfdmVjdG9yCgpoZWFkKHNpZ19lbnRyZXopCgojIHJlbW92ZSBkdXBzCmR1cHM8LXVuaXF1ZShuYW1lcyhzaWdfZW50cmV6W3doaWNoKGR1cGxpY2F0ZWQobmFtZXMoc2lnX2VudHJleikpKV0pKQpzaWdfZW50cmV6PC1zaWdfZW50cmV6WyEobmFtZXMoc2lnX2VudHJleikgJWluJSBkdXBzKV0KCgpgYGAKCgoKYGBge3J9CgoKI2RlPSBhcy52ZWN0b3Ioc2lnX2VudHJleikKCiNkZSA9IHNvcnQoZGUsIGRlY3JlYXNpbmcgPSBGQUxTRSkKCiMgdGhpcyBzdGVwIHRha2VzIHRpbWUKCnNwaWFfcmVzdWx0IDwtIHNwaWEoZGU9c2lnX2VudHJleiwgYWxsPWJhY2tncm91bmRfZW50cmV6LCBvcmdhbmlzbT0ibW11IiwgcGxvdHM9RkFMU0UpCgpgYGAKCmBgYHtyfQp3cml0ZS5jc3Yoc3BpYV9yZXN1bHQsIGZpbGUgPSAic3BpYV9yZXN1bHRfdGdfYWdlLmNzdiIpCgpgYGAKCgoKYGBge3J9CgojIHZpZXcgb25lIHJlY29yZCBhdCBhIHRpbWUKCnN1YnNldChzcGlhX3Jlc3VsdCwgSUQgPT0gIjA0NzI3IikKCmBgYAoKYGBge3J9CgpoZWFkKHJlczFfb3JkZXJlZCkKbm9ybV9jb3VudHNfdG9wXzQwID0gbm9ybWFsaXplZGNvdW50cy5tYXRyaXhbcm93Lm5hbWVzKGhlYWQocmVzMV9vcmRlcmVkLCA0MCkpLCBdCmBgYAoKYGBge3J9Cm5yb3cobm9ybV9jb3VudHNfdG9wXzQwKQpgYGAKCmBgYHtyfQpoZWFkKGRlc2lnbl9tYXRyaXgpCgphbm5vdGF0aW9uX2NvbHVtbnM8LWRlc2lnbl9tYXRyaXgKCnJvdy5uYW1lcyhhbm5vdGF0aW9uX2NvbHVtbnMpIDwtIGNvbG5hbWVzKG5vcm1fY291bnRzX3RvcF80MCkKCmxpYnJhcnkocGhlYXRtYXApCmBgYAoKYGBge3J9Cgp0aWZmKCJIZWF0bWFwX1dUX1RHX3ZzX3J0ZzQ1MTAudGlmZiIsIHdpZHRoID0gNywgaGVpZ2h0ID0gNSwgdW5pdHMgPSAnaW4nLCByZXMgPSAzMDApCnBoZWF0bWFwKG5vcm1fY291bnRzX3RvcF80MCwgY29sb3I9Y29sb3JSYW1wUGFsZXR0ZShjKCJ3aGl0ZSIsICJsYXZlbmRlciIsICJkYXJrb3JjaGlkMSIpKSgzMCksIHNjYWxlPSJyb3ciLCBjbHVzdGVyX2NvbHMgPSBULCBzaG93X3Jvd25hbWVzID0gVCxmb250c2l6ZSA9IDcsZm9udHNpemVfcm93ID0gNCwgZm9udHNpemVfY29sID0gNCxsYWJlbHNfcm93ID0gcm93bmFtZXMoZGlzdHMpLGFubm90YXRpb25fY29sID1hbm5vdGF0aW9uX2NvbHVtbnMsbWFpbj0nRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIGluIHJUZzQ1MTAgbWljZSBhdCAyIGFuZCA4IG1vbnRocyBvbGQnICkKZGV2Lm9mZigpCmBgYAoKCg==